package com.kuaimacode.kframework.api.controller;

import com.alibaba.fastjson.JSON;
import com.kuaimacode.kframework.api.jwt.JwtTokenUtil;
import com.kuaimacode.kframework.api.jwt.JwtUserFactory;
import com.kuaimacode.kframework.api.service.*;
import com.kuaimacode.kframework.api.service.weixin.WeixinApiService;
import com.kuaimacode.kframework.api.util.IpUtil;
import com.kuaimacode.kframework.api.util.MaskUtil;
import com.kuaimacode.kframework.api.vo.AppMenuVO;
import com.kuaimacode.kframework.api.vo.request.*;
import com.kuaimacode.kframework.api.vo.response.*;
import com.kuaimacode.kframework.common.Constant;
import com.kuaimacode.kframework.common.JsonResult;
import com.kuaimacode.kframework.component.ComponentUtil;
import com.kuaimacode.kframework.component.SmsRecordService;
import com.kuaimacode.kframework.component.SmsSendService;
import com.kuaimacode.kframework.enums.WeixinRespCodeEnum;
import com.kuaimacode.kframework.exception.ErrorEnum;
import com.kuaimacode.kframework.exception.ServerInternalErrorException;
import com.kuaimacode.kframework.mybatis.models.agent.SysAgent;
import com.kuaimacode.kframework.mybatis.models.index.BootstrapImg;
import com.kuaimacode.kframework.mybatis.models.user.User;
import com.kuaimacode.kframework.util.DictUtil;
import com.kuaimacode.kframework.util.ValidUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import sun.net.www.http.HttpClient;
import weixin.popular.bean.sns.Jscode2sessionResult;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.validation.Valid;
import java.io.IOException;
import java.util.*;

@Slf4j
@RestController
@RequestMapping("")
@SessionAttributes("user")
@Api(tags = "首页相关信息", description = "首页相关信息api")
public class IndexController extends BaseController {

    @Autowired
    private UserService userService;
    @Autowired
    private JwtTokenUtil jwtTokenUtil;
    @Autowired
    private BootstrapImgService bootstrapImgService;
    @Autowired
    private SmsSendService smsSendService;
    @Autowired
    private AgentService agentService;
    @Autowired
    private SmsRecordService smsRecordService;
    @Autowired
    private IndexService indexService;
    @Autowired
    private ComponentUtil componentUtil;
    @Autowired
    private AppMenuService menuService;
    @Autowired
    private WeixinApiService weixinApiService;
    @Autowired
    private AliTokenService aliTokenService;

    @Autowired
    private SysParamService sysParamService;

    @Value("${weixin.applets.appId}")
    private String weixinAppId;
    @Value("${weixin.applets.appSecret}")
    private String weixinSecret;

    @ApiOperation(value = "获取服务器时间")
    @GetMapping("/time")
    public ResponseEntity<?> getTime() {
        return ResponseEntity.status(HttpStatus.OK).body(new Date());
    }


    @ApiOperation(value = "创建字典", notes = "字典值字符串：code:value:remark:reserved,code:value:remark:reserved")
    @GetMapping("/creatDict")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "title", value = "字典名称", required = true, dataType = "string"),
            @ApiImplicitParam(name = "name", value = "字典标识", required = true, dataType = "string"),
            @ApiImplicitParam(name = "remark", value = "字典备注", dataType = "string"),
            @ApiImplicitParam(name = "values", value = "字典值字符串", required = true, dataType = "string")
    })
    public JsonResult creatDict(@RequestParam String title, @RequestParam String name, @RequestParam String remark, @RequestParam String values) {
        String[] args = null;
        if (values != null && values.length() > 0) {
            args = values.split(",");
        }
        try {
            DictUtil.createDict(title, name, remark, args);
        } catch (Exception e) {
            return JsonResult.failure(e.getMessage());
        }
        return JsonResult.success();
    }

    @ApiOperation(value = "校验手机号是否已注册")
    @PostMapping("/isRegister/{phone}")
    @ApiImplicitParam(name = "phone", value = "手机号", required = true, dataType = "string")
    public JsonResult<Boolean> isRegister(@PathVariable String phone) {
        if (!ValidUtil.isMobile(phone)) {
            throw new ServerInternalErrorException(ErrorEnum.MOBILE_ERROR);
        }
        return JsonResult.success(userService.selectByPhone(phone) != null);
    }

    @ApiOperation(value = "微信登陆")
    @PostMapping("/threeLogin")
    @ApiImplicitParam(name = "loginReq", value = "loginReq实体", required = true, dataType = "ThreeLoginReq")
    public JsonResult<ThreeLoginResp> threeLogin(@Valid @RequestBody ThreeLoginReq loginReq, HttpServletRequest request) {
        //根据openid查询用户
        User user = userService.selectByUnionId(loginReq.getUnionId());
        if (user == null) {
            user = new User();
            user.setOpenId(loginReq.getOpenId());
            user.setUnionId(loginReq.getUnionId());
            user.setEnabled(1);
            user.setUsername(loginReq.getOpenId());
            userService.add(user);
        }
        userService.updateLastLoginInfo(user.getId(), IpUtil.getIpAddress(request));
        ThreeLoginResp loginResp = new ThreeLoginResp();
        //已绑定手机号
        loginResp.setToken(jwtTokenUtil.generateToken(JwtUserFactory.create(user, new ArrayList<>())));
        userService.updateUserToken(user.getId(), loginResp.getToken());
        if (StringUtils.isNotBlank(user.getPhone())) {
            loginResp.setBind(true);
            loginResp.setIsProtocol(user.getIsProtocol());
            return JsonResult.success(loginResp);
        } else {
            loginResp.setBind(false);
            return JsonResult.success(loginResp);
        }
    }

    @ApiOperation(value = "一键登录")
    @PostMapping("/accessoLogin")
    @ApiImplicitParam(name = "loginReq", value = "loginReq实体", required = true, dataType = "AccessoLoginReq")
    public JsonResult<AccessoLoginResp> accessoLogin(@Valid @RequestBody AccessoLoginReq loginReq) {
        String mobile = Optional.ofNullable(aliTokenService.getMobile(loginReq)).orElseThrow(() -> new ServerInternalErrorException(ErrorEnum.ALI_MOBILE_GET_ERROR));
        User user = userService.selectByPhone(mobile);
        if (user == null) {
            user = new User();
            user.setUsername(mobile);
            user.setNickname("用户" + MaskUtil.interceptBack4(mobile));
            user.setPhone(mobile);
            user.setEnabled(1);
            user.setIsProtocol((short) 1);
            userService.add(user);
        }
        AccessoLoginResp loginResp = new AccessoLoginResp();
        loginResp.setToken(jwtTokenUtil.generateToken(JwtUserFactory.create(user, new ArrayList<>())));
        loginResp.setIsProtocol(user.getIsProtocol());
        loginResp.setMobile(mobile);
        userService.updateUserToken(user.getId(), loginResp.getToken());
        userService.updateLastLoginInfo(user.getId(), IpUtil.getIpAddress(request));
        return JsonResult.success(loginResp);
    }

    @ApiOperation(value = "小程序登陆")
    @PostMapping("/appletsLogin")
    @ApiImplicitParam(name = "loginReq", value = "loginReq实体", required = true, dataType = "AppletsLoginReq")
    public JsonResult<AppletsLoginResp> appletsLogin(@Valid @RequestBody AppletsLoginReq loginReq) {
        Jscode2sessionResult result = weixinApiService.getMsgByAppletsLoginCode(loginReq.getCode());
        if (WeixinRespCodeEnum.SUCCESS.getValue().equals(result.getErrcode())) {
            User user = userService.selectByUnionId(result.getUnionid());
            //用户不存在，则添加用户
            if (user == null) {
                user = new User();
                user.setUsername("微信用户");
                user.setPhone("");
                user.setOpenId(Optional.ofNullable(result.getOpenid()).orElse(""));
                user.setUnionId(result.getUnionid());
                user.setEnabled(1);
                userService.save(user);
            }
            AppletsLoginResp loginResp = new AppletsLoginResp();
            loginResp.setToken(jwtTokenUtil.generateToken(JwtUserFactory.create(user, new ArrayList<>())));
            loginResp.setIsProtocol(user.getIsProtocol());
            if (StringUtils.isNotBlank(user.getPhone())) {
                loginResp.setBind(true);
            } else {
                loginResp.setBind(false);
            }
            userService.updateUserToken(user.getId(), loginResp.getToken());
            return JsonResult.success(loginResp);
        }
        throw new ServerInternalErrorException(result.getErrcode(), result.getErrmsg());
    }

    @ApiOperation(value = "小程序登陆（新）")
    @PostMapping("/appletsLoginNew")
    @ApiImplicitParam(name = "loginNewReq", value = "loginNewReq实体", required = true, dataType = "AppletsLoginNewReq")
    public JsonResult<AppletsLoginResp> appletsLoginNew(@Valid @RequestBody AppletsLoginNewReq loginReq, HttpServletRequest request) {
        User user = userService.appletsLoginNew(loginReq);
        AppletsLoginResp loginResp = new AppletsLoginResp();
        loginResp.setToken(jwtTokenUtil.generateToken(JwtUserFactory.create(user, new ArrayList<>())));
        loginResp.setIsProtocol(user.getIsProtocol());
        loginResp.setBind(true);
        userService.updateUserToken(user.getId(), loginResp.getToken());
        userService.updateLastLoginInfo(user.getId(), IpUtil.getIpAddress(request));
        return JsonResult.success(loginResp);
    }

    @ApiOperation(value = "手机号验证码登陆")
    @PostMapping("/verifyCodeLogin")
    @ApiImplicitParam(name = "loginReq", value = "loginReq实体", required = true, dataType = "VerifyCodeLoginReq")
    public JsonResult<BaseLoginResp> verifyCodeLogin(@Valid @RequestBody VerifyCodeLoginReq loginReq, HttpServletRequest request) {
        log.info("verifyCodeLogin req: {}", JSON.toJSONString(loginReq));
        //验证码校验成功
        if (smsRecordService.validVerifyCode(loginReq.getPhone(), loginReq.getVerifyCode())) {
            User user;
            if (StringUtils.isNotBlank(loginReq.getUnionId())) {
                user = userService.selectByUnionId(loginReq.getUnionId());
                if (user == null) {
                    user = userService.selectByPhone(loginReq.getPhone());
                    if (user == null) {
                        user = new User();
                        user.setUsername(loginReq.getPhone());
                        user.setNickname("用户" + MaskUtil.interceptBack4(loginReq.getPhone()));
                        user.setUnionId(loginReq.getUnionId());
                        user.setOpenId(loginReq.getOpenId());
                        user.setPhone(loginReq.getPhone());
                        user.setEnabled(1);
                        user.setIsProtocol((short) 1);
                        userService.add(user);
                    } else if (StringUtils.isBlank(user.getOpenId())) {
                        user.setUnionId(loginReq.getUnionId());
                        user.setOpenId(loginReq.getOpenId());
                        userService.updateById(user);
                    }
                } else if (StringUtils.isNotBlank(user.getPhone())) {
                    throw new ServerInternalErrorException(ErrorEnum.OPEN_ID_NOT_EXISTS_OR_HAS_BIND);
                } else {
                    user = userService.selectByPhone(loginReq.getPhone());
                    if (user != null) {
                        userService.deleteByUniondId(loginReq.getUnionId(), loginReq.getOpenId());
                    }
                    //绑定手机号
                    user.setPhone(loginReq.getPhone());
                    user.setUsername(loginReq.getPhone());
                    user.setNickname("用户" + MaskUtil.interceptBack4(loginReq.getPhone()));
                    user.setOpenId(loginReq.getOpenId());
                    user.setUnionId(loginReq.getUnionId());
                    if (!userService.updateById(user)) {
                        throw new ServerInternalErrorException(ErrorEnum.PHONE_BIND_ERROR);
                    }
                }
            } else {
                //非绑定手机号场景，如果已存在手机号则登陆成功，不存在则新增账号
                user = userService.selectByPhone(loginReq.getPhone());
                if (user == null) {
                    user = new User();
                    user.setUsername(loginReq.getPhone());
                    user.setNickname("用户" + MaskUtil.interceptBack4(loginReq.getPhone()));
                    user.setPhone(loginReq.getPhone());
                    user.setEnabled(1);
                    user.setIsProtocol((short) 1);
                    userService.add(user);
                }
            }
            BaseLoginResp loginResp = new BaseLoginResp();
            loginResp.setToken(jwtTokenUtil.generateToken(JwtUserFactory.create(user, new ArrayList<>())));
            loginResp.setIsProtocol(user.getIsProtocol());
            userService.updateUserToken(user.getId(), loginResp.getToken());
            userService.updateLastLoginInfo(user.getId(), IpUtil.getIpAddress(request));
            return JsonResult.success(loginResp);
        }
        throw new ServerInternalErrorException(ErrorEnum.VERIFY_CODE_VALID_ERROR);
    }

    @ApiOperation(value = "获取广告页信息")
    @PostMapping("/getAdsPage")
    public JsonResult<List<BootstrapImg>> getAdsPage() {
        List<BootstrapImg> list = new ArrayList<>();
        List<BootstrapImg> imgs = bootstrapImgService.getAdsPage();
        for(BootstrapImg img:imgs){
            String paths = img.getImgUrl();
            if(paths!=null && !"".equals(paths)){
                for(String path:paths.split(",")){
                    BootstrapImg bootstrapImg = new BootstrapImg();
                    bootstrapImg.setImgUrl(componentUtil.convertImgUrl(path));
                    list.add(bootstrapImg);
                }
            }
        }
        return JsonResult.success(list) ;
    }
    @ApiOperation(value = "获取引导页信息")
    @PostMapping("/getGuidePage")
    public JsonResult<List<BootstrapImg>> getGuidePage() {
        List<BootstrapImg> imgs = bootstrapImgService.getGuidePage();
        List<BootstrapImg> list = new ArrayList<>();
        for(BootstrapImg img:imgs){
            String paths = img.getImgUrl();
            if(paths!=null && !"".equals(paths)){
                for(String path:paths.split(",")){
                    BootstrapImg bootstrapImg = new BootstrapImg();
                    bootstrapImg.setImgUrl(componentUtil.convertImgAdminUrl(path));
                    list.add(bootstrapImg);
                }
            }
        }
        return JsonResult.success(list);
    }

    @ApiOperation(value = "发送验证码")
    @PostMapping("/sendVerifyCode")
    public JsonResult sendVerifyCode(@RequestBody Map<String, String> mobileMap) {
        log.info("send verify code mobile: {}", JSON.toJSONString(mobileMap));
        if (!ValidUtil.isMobile(mobileMap.get("mobile"))) {
            throw new ServerInternalErrorException(ErrorEnum.MOBILE_ERROR);
        }
        //发送验证码
        if (smsSendService.sendLoginVerifyCode(mobileMap.get("mobile"))) {
            return JsonResult.success();
        } else {
            return JsonResult.failure(ErrorEnum.VERIFY_CODE_SEND_ERROR.getCode(),
                    ErrorEnum.VERIFY_CODE_SEND_ERROR.getMsg());
        }
    }

    @ApiOperation(value = "绑定用户并返回菜单信息", notes = "用户切换位置（前台做必要校验，所在区县发生变化后再调用该接口，不用每次位置变化都调用），并返回app头部菜单数据，" +
            "isOpen  1 表示当前区县已开通服务， 0 表示未开通 ")
    @GetMapping("/bindAndGetAgnetMenu/{areaCode}")
    @ApiImplicitParam(name = "areaCode", value = "区县行政区划代码", required = true, dataType = "string")
    public JsonResult bindAndGetAgnetMenu(@PathVariable String areaCode, HttpServletRequest request) {
        SysAgent agent = agentService.getAgentInfoById(areaCode);
        Map map = new HashMap<String, String>();
        HttpSession session = request.getSession();
        if (agent != null) {
            map.put("isOpen", "1");
        } else {
            map.put("isOpen", "0");
        }
        List<AppMenuVO> appMenuVOS = menuService.getMenu(areaCode);
        map.put("menus",appMenuVOS);
        return JsonResult.success(map);
    }


    @ApiOperation(value = "获取首页数据")
    @PostMapping("/index")
    @ApiImplicitParams({
        @ApiImplicitParam(name = "userType", value = "0 普通用户 1 师傅", required = true, dataType = "string"),
        @ApiImplicitParam(name = "agentId", value = "用户当前所在区县行政区划代码",required = false,dataType = "",defaultValue = "")
    })
    public JsonResult<IndexResp> index(@RequestParam Integer userType,String agentId) {
        SysAgent agent = agentService.getAgentInfoById(agentId);
        IndexResp indexResp = indexService.index(getUserId(), userType, agentId);
        if(agent == null || agent.getStat() == Constant.AgentStatEnum.OFF.getCode()){
            indexResp.setIsOpen(Constant.IsNotEnum.NO.getCode().toString());
        }else{
            indexResp.setIsOpen(Constant.IsNotEnum.YES.getCode().toString());
        }
        return JsonResult.success(indexResp);
    }

    @ApiOperation(value = "获取系统参数")
    @PostMapping("/getSysParam/{paramName}")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "paramName", value = "参数名称", required = true, dataType = "string")
    })
    public JsonResult getSysParam(@PathVariable String paramName) {

        String value = sysParamService.findByNameAndAgent(paramName,Constant.DEFAULT_AGENT_ID);
        return JsonResult.success(value);
    }

    @ApiOperation(value = "app下载地址链接", notes = "app下载地址链接")
    @GetMapping("/getAppDownloadInfo")
    public JsonResult<AppDownloadInfo> getAppDownloadInfo(){
        AppDownloadInfo appDownloadInfo = new AppDownloadInfo();
        String iosDownloadUrl = sysParamService.findByNameAndAgent("IOS_DOWNLOAD_URL",Constant.DEFAULT_AGENT_ID);
        String androidDownloadUrl = sysParamService.findByNameAndAgent("ANDROID_DOWNLOAD_URL",Constant.DEFAULT_AGENT_ID);

        appDownloadInfo.setIosDownloadURL(iosDownloadUrl);
        appDownloadInfo.setAndroidDownloadURL(androidDownloadUrl);


        CloseableHttpClient client =null;

        try {
            client =   HttpClients.createDefault();
            String  url ="http://qr.liantu.com/api.php?&w=300&text="+iosDownloadUrl;
            String iosImgUrl = indexService.httpGetImg(client,url,"ios");
            appDownloadInfo.setIosQrCode(componentUtil.convertImgUrl(iosImgUrl));

            url ="http://qr.liantu.com/api.php?&w=300&text="+androidDownloadUrl;
            String androidImgUrl = indexService.httpGetImg(client,url,"android");
            appDownloadInfo.setAndroidQrCode(componentUtil.convertImgUrl(androidImgUrl));
            return JsonResult.success(appDownloadInfo);
        } catch (Exception e) {
            e.printStackTrace();
        }finally{
            if(client!=null){
                try {
                    client.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return JsonResult.failure("获取下载链接失败");

    }





}
